#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygtk
pygtk.require20
import gtk
gtk.gdk.threads_init()

import expgui
import expdb
import exputils
import i18n

import datetime
import time

from threading import Thread
from Queue import Queue


class Expenses:
    def __init__(self):
        self._init_gui()
        
        self._init_request_system()
        self._init_model()
        self._cfg = exputils.ConfigManager('exp.conf')
        self._cfg.register(self._main_window, 'main_window')
        self._cfg.restore()
    
    #----Funkcje obsługujące inicjalizację programu--------------------------------------------#
    def _init_gui(self):
        """Funkcja odpowiedzialna za załadowanie okien i innych
        elementów graficznych programu."""
        #załadowanie głównego okna i okien dialogowych
        self._main_window = expgui.MainWindow()
        self._main_window.add_listener(self, 'main_window')
        self._ae_dialog  = expgui.AddEditDialog()
        self._mi_dialog = expgui.MonthDialog()
        self._mi_dialog.add_listener(self, 'mi_dialog')
        #załadowanie ikony w tray'u
        self._tray_icon = expgui.TrayIcon(iconname='accessories-text-editor', tooltip=_('Budget'))
        self._tray_icon.add_listener(self, 'tray')
    
    def _init_model(self):
        """Funkcja odpowiedzialna za otwarcie połączenia z bazą danych."""
        def threaded():
            self._db = expdb.ExpensesDatabase('exp_db')
            self._db.add_listener(self, 'model')
            self._db.set_day(datetime.date.today())
            #self._db.import_from_v10('/home/krzysiek/programy/pyexpenses/exp_db')
        self.execute_threaded(threaded)
    
    def _init_request_system(self):
        """Funkcja odpowiedzialna za włączenie systemu obsługi
        wykonywania zadań w tle."""
        self._queue = Queue()
        self._request_thread = Thread(target=self._requests_loop)
        self._request_thread.start()
    
    #----Funkcje obsługujące system wykonywania zadań w tle------------------------------------#
    def _requests_loop(self):
        """Pętla systemu wykonywania zadań w tle."""
        while True:
            function, data = self._queue.get()
            if function is None:
                self._queue.task_done()
                break
            gtk.gdk.threads_enter()
            if not data:
                function()
            else:
                function(data)
            gtk.gdk.threads_leave()
            self._queue.task_done()
    
    def execute_threaded(self, function, data=None):
        """Umożliwia wykonanie podanej funkcji w tle."""
        self._queue.put((function, data))
    
    #----Funkcje obsługujące zdarzenia z ikony w tray'u----------------------------------------#
    def on_tray_close(self, empty):
        self.execute_threaded(None)
        self._request_thread.join(10.0)
        time.sleep(0.5)
        
        self._cfg.store()
        
        gtk.main_quit()
    
    def on_tray_about(self, empty):
        print 'about will be here'
    
    def on_tray_add_item(self, empty):
        self._add_item(datetime.date.today())
    
    def on_tray_month_info(self, empty):
        self._show_month_info(datetime.date.today())
    
    def on_tray_clicked(self, empty):
        if self._main_window.is_visible():
            self._main_window.hide()
        else:
            self._main_window.show()
    
    #----Funkcje obsługujące zdarzenia z bazy danych-------------------------------------------#
    def on_model_data_changed(self, empty):
        def threaded():
            self._main_window.set_data(self._db.get_positions_by_day(), self._db.get_day_summary())
        self.execute_threaded(threaded)
    
    def on_model_day_changed(self, day):
        def threaded():
            self._main_window.set_data(self._db.get_positions_by_day(), self._db.get_day_summary())
        self._main_window.set_day(day.strftime('%A, %x'))
        self.execute_threaded(threaded)
    
    #----Funkcje obsługujące zdarzenia z okna dialogowego podsumowania miesiąca----------------#
    def on_mi_dialog_date_changed(self, date):
        def threaded(date):
            self._mi_dialog.set_data(self._db.get_month_summary(date))
        self.execute_threaded(threaded, date)
    
    #----Funkcje obsługujące zdarzenia z głównego okna-----------------------------------------#
    def on_main_window_nextday(self, empty):
        self._db.set_next_day()
    
    def on_main_window_prevday(self, empty):
        self._db.set_prev_day()
    
    def on_main_window_today(self, empty):
        self._db.set_day(datetime.date.today())
    
    def on_main_window_month_info(self, empty):
        self._show_month_info()
    
    def on_main_window_add_item(self, empty):
        self._add_item()

    def on_main_window_edit_item(self, item):
        def threaded(rowid):
            result = self._ae_dialog.show_modal(_('Edytuj pozycję'), self._db.get_position(rowid))
            if result:
                self._db.update_position(rowid, *result)
        rowid = self._main_window.get_selected_rowid()
        if rowid:
            self.execute_threaded(threaded, rowid)
    
    def on_main_window_delete_item(self, empty):
        def threaded(rowid):
            self._db.remove_position(rowid)
        rowid = self._main_window.get_selected_rowid()
        if rowid:
            self.execute_threaded(threaded, rowid)

    def on_main_window_close(self, empty):
        self._main_window.hide()


    #----Inne funkcje--------------------------------------------------------------------------#
    def _add_item(self, date=None):
        def threaded(data):
            self._db.add_position(*data)
        if not date:
            date = self._db.get_day()
        result = self._ae_dialog.show_modal(_('Dodaj pozycję (%s)') % date.strftime('%A, %x'))
        if result:
            self.execute_threaded(threaded, result)

    def _show_month_info(self, date=None):
        def threaded(date):
            self._mi_dialog.show(date)
        if not date:
            date = self._db.get_day()
        self.execute_threaded(threaded, date)

if __name__ == '__main__':
    app = Expenses()
    gtk.main()